# -*- coding: utf-8 -*-
from PyQt4 import QtGui,QtCore
from ui_tcptab import Ui_tcptab
from twisted.internet.protocol import ClientFactory
import re
try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s
from twisted.internet import protocol
from twisted.internet import reactor

from xml.etree import ElementTree

class EchoClient(protocol.Protocol):    
    def __init__(self,widget):
        self.widget = widget
    
    def connectionMade(self):
        self.widget.connectionMade(self)
    
    def dataReceived(self, data):        
        self.widget.dataReceived(self, data)

class EchoFactory(protocol.ClientFactory):
    def __init__(self,widget):
        self.widget = widget
        
    def startedConnecting(self, connector):
        pass
    
    def clientConnectionFailed(self, connector, reason):
        self.widget.connectionLost(reason)        
    
    def clientConnectionLost(self, connector, reason):
        self.widget.connectionLost(reason)        

    def buildProtocol(self, addr):
        p = EchoClient(self.widget)
        p.factory = self
        return p
    
class tcp_tab(QtGui.QWidget):
    def __init__(self, tabmanager, address, logic_mod):
        QtGui.QWidget.__init__(self)
        self.ui_mod = Ui_tcptab()
        self.ui_mod.setupUi(self)
        
        self.ui_mod.edit_recv = self.recv_edit(self) 
        self.ui_mod.edit_recv.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.ui_mod.edit_recv.setReadOnly(True)
        self.ui_mod.edit_recv.setObjectName(_fromUtf8("edit_recv"))
        self.ui_mod.gridLayout.addWidget(self.ui_mod.edit_recv, 1, 0, 1, 6)
        
        self.logic_mod = None 
        if (logic_mod):    
            self.logic_mod = logic_mod
            self.logic_mod.tcpmod = self
        
        self.ui_mod.btn_send.clicked.connect(self.on_send_clicked)
        self.ui_mod.btn_new.clicked.connect(self.on_new_clicked)
        self.ui_mod.btn_connect.clicked.connect(self.on_connect_clicked)
        
        self.ui_mod.btn_add.clicked.connect(self.on_add_clicked)
        self.ui_mod.btn_check.clicked.connect(self.on_check_clicked)
        self.ui_mod.btn_follow.clicked.connect(self.on_follow_clicked)
        self.ui_mod.btn_giveup.clicked.connect(self.on_giveup_clicked)
        
        QtCore.QObject.connect(self,QtCore.SIGNAL("pingSig()"), 
                               self.on_ping)
        
        QtCore.QObject.connect(self,QtCore.SIGNAL("dataReceivedSig(QString)"), 
                               self.dataReceivedSlot)
        QtCore.QObject.connect(self,QtCore.SIGNAL("connectionMadeSig()"), 
                               self.connectionMadeSlot)
        QtCore.QObject.connect(self,QtCore.SIGNAL("connectionLostSig(QString)"), 
                               self.connectionLostSlot)
        
        self.tabmanager = tabmanager
        self.client_factory = EchoFactory(self)
        self.echoclient = None
        self.ip = None
        self.port = None
        self.ui_mod.edit_connect.setText(str(address))
        self.sendbuf = []
    
    def ping(self):
        self.emit(QtCore.SIGNAL('pingSig()'))
    
    def on_ping(self):
        self.ui_mod.edit_send.setText("<ping id='"+str(self.uid)+"ping'/>")
        self.on_send_clicked()
        
    def on_new_clicked(self):
        self.tabmanager.on_new_clicked()
        
    def on_add_clicked(self):
        self.ui_mod.edit_send.setText("<cuseradd><chip>"+str(self.addless)+"</chip></cuseradd>")        
    
    def on_check_clicked(self):
        self.ui_mod.edit_send.setText("<cuseradd><chip>0</chip></cuseradd>")
        self.on_send_clicked()
            
    def on_follow_clicked(self):
        self.ui_mod.edit_send.setText("<cuseradd><chip>"+str(self.turnless)+"</chip></cuseradd>")
        self.on_send_clicked()
            
    def on_giveup_clicked(self):
        self.ui_mod.edit_send.setText("<cusergiveup/>")
        self.on_send_clicked()
                
    def on_connect_clicked(self):
        if (self.ip and self.port):
            if (self.echoclient):
                self.ui_mod.btn_connect.setEnabled(False)
                self.ui_mod.btn_connect.setText(QtGui.QApplication.translate("tcptestorui", "断开中", None, QtGui.QApplication.UnicodeUTF8))                    
                self.echoclient.transport.loseConnection()
            return
        pattern = re.compile(r"(?P<ip>.*):(?P<port>\d+)")
        addrstr = str(self.ui_mod.edit_connect.document().toPlainText().toAscii())
        addrmatch = pattern.match(addrstr)
        if (addrmatch):
            self.ip = addrmatch.group("ip")                
            self.port = addrmatch.group("port")
            intport = int(self.port)
            reactor.connectTCP(self.ip, intport, self.client_factory)
            self.ui_mod.btn_connect.setEnabled(False)
            self.ui_mod.btn_connect.setText(QtGui.QApplication.translate("tcptestorui", "连接中", None, QtGui.QApplication.UnicodeUTF8))
    
    def connect(self):
        self.on_connect_clicked()
    
    def send_data(self, text):
        self.ui_mod.edit_send.setText(text)
        if (self.echoclient):
            Sendstr = text
            self.echoclient.transport.write(Sendstr)
            self.ui_mod.edit_recv.append("send:\n"+Sendstr)
        else:
            self.sendbuf.append(text)
    
    def on_send_clicked(self):
        if (self.echoclient):
            Sendstr = str(self.ui_mod.edit_send.document().toPlainText().toUtf8())
            self.echoclient.transport.write(Sendstr)
            self.ui_mod.edit_recv.append("send:\n"+Sendstr)     
    
    def on_tab_closed(self):
            if (self.echoclient):
                self.echoclient.transport.loseConnection()

    def connectionMade(self, echoclient):
        self.echoclient = echoclient
        self.emit(QtCore.SIGNAL('connectionMadeSig()'))
                    
    def connectionMadeSlot(self):
        self.ui_mod.btn_connect.setEnabled(True)
        self.ui_mod.btn_connect.setText(QtGui.QApplication.translate("tcptestorui", "断开", None, QtGui.QApplication.UnicodeUTF8))             
        self.tabmanager.ui_mod.tabWidget.setTabText(
        self.tabmanager.ui_mod.tabWidget.indexOf(self), \
        QtGui.QApplication.translate("tcptestorui",\
        self.ip+":"+self.port+"-已连接", None, QtGui.QApplication.UnicodeUTF8))
        self.ui_mod.edit_recv.append(self.ip+":"+self.port+u"已连接") 
        
        for senditem in self.sendbuf:
            self.send_data(senditem)    
        self.sendbuf = []      
        
        
        self.uid = ""
        self.chairid = -1
        self.turnless = 0
        self.gold = 0
        self.currentuser = -1
        self.addless = 0

    def dataReceived(self, echoclient, data):
        if (self.echoclient == echoclient):
            self.emit(QtCore.SIGNAL('dataReceivedSig(QString)'), unicode(data))
        
        
    def dataReceivedSlot(self, unicodedata):  
        # 解析服务器发来的消息
        #self.ui_mod.edit_recv.append(str("recv:"))
        #self.ui_mod.edit_recv.append(unicodedata)
        #if (u"<ping/>"!=unicodedata):
            #self.send_data("<ping/>")
        
        # 解析success结点
        try:
            #datastr = str(unicodedata)            
            datastr = unicode(unicodedata,'utf-8') 
            
            self.ui_mod.edit_recv.append("recv:\n"+datastr)                
            
            pos1 = datastr.find("<success")
            pos2 = datastr.find("</success>")
            
            if (pos1==-1 or pos2==-1):            		
            		pos1 = datastr.find("<smatchdesk")
            		pos2 = datastr.find("</smatchdesk>")
            		
            if (pos1!=-1 and pos2!=-1):
                xmldata = datastr[pos1:pos2+"</success>".__len__()]
                
                self.ui_mod.edit_recv.append(str("pos1:"+str(pos1)+",pos2:"+str(pos2)+"\nparse:"))
                self.ui_mod.edit_recv.append(xmldata)
                
                root = ElementTree.fromstring(xmldata)
                lst_node = root.getiterator("success")
                for node in lst_node:
                    uid_node = node.getiterator("uid")
                    for unode in uid_node:
                        self.tabmanager.ui_mod.tabWidget.setTabText(
                            self.tabmanager.ui_mod.tabWidget.indexOf(self), \
                            QtGui.QApplication.translate("tcptestorui",\
                            unode.text, None, QtGui.QApplication.UnicodeUTF8)) 
                        self.send_data("<csitdown><chairid>"+str(int(unode.text) % 9)+\
                                       "</chairid></csitdown>")
                        self.uid = unode.text
                        break  
                    
                    gold_node = node.getiterator("money") 
                    for gnode in gold_node:
                        self.gold = int(gnode.text)
                        break  

                    turnless_node = node.getiterator("turnless")
                    for tnode in turnless_node:
                        self.turnless = int(tnode.text)
                        break             
                    
                    addless_node = node.getiterator("addless")
                    for alnode in addless_node:
                        self.addless = int(alnode.text)
                        break
                
                    games_node = node.getiterator("sgamestate")
                    for gamesn in games_node:
                        users_node = gamesn.getiterator("users")
                        for usnode in users_node:
                            user_nodes = usnode.getiterator("item")
                            for item in user_nodes:
                                chairid = int(item.get("chairid"))
                                money = int(item.get("money"))
                                if (item.get("uid")==self.uid):
                                    self.chairid = chairid
                                    self.gold = money
                                    break
                            break
                        
                        break
                    
                    break   
        except:
            pass  
        
        # 解析ssitdown结点
        try:
            datastr = str(unicodedata)
            pos1 = datastr.find("<ssitdown")
            pos2 = datastr.find("</ssitdown>")
            if (pos1!=-1 and pos2!=-1):
                xmldata = datastr[pos1:pos2+"</ssitdown>".__len__()]
                
                self.ui_mod.edit_recv.append(str("pos1:"+str(pos1)+",pos2:"+str(pos2)+"\nparse:"))
                self.ui_mod.edit_recv.append(xmldata)
                
                root = ElementTree.fromstring(xmldata)
                lst_node = root.getiterator("ssitdown")
                for node in lst_node:
                    chairid_node = node.getiterator("chairid")
                    for cnode in chairid_node:                
                        self.chairid = int(cnode.text)
                        break
                    break
        except:
            pass        
        
        # 解析sgamebegin结点
        try:
            datastr = str(unicodedata)
            pos1 = datastr.find("<sgamebegin")
            pos2 = datastr.find("</sgamebegin>")
            if (pos1!=-1 and pos2!=-1):
                xmldata = datastr[pos1:pos2+"</sgamebegin>".__len__()]
                
                self.ui_mod.edit_recv.append(str("pos1:"+str(pos1)+",pos2:"+str(pos2)+"\nparse:"))
                self.ui_mod.edit_recv.append(xmldata)
                
                root = ElementTree.fromstring(xmldata)
                lst_node = root.getiterator("sgamebegin")
                for node in lst_node:
                    nodes = node.getiterator("currentuser")
                    for cnode in nodes:                
                        self.currentuser = int(cnode.text)
                        break
                                    
                    users_node = node.getiterator("users")
                    for usnode in users_node:
                        user_nodes = usnode.getiterator("item")
                        for item in user_nodes:
                            chairid = int(item.get("chairid"))
                            money = int(item.get("money"))
                            if (item.get("uid")==self.uid):
                                self.chairid = chairid
                                self.gold = money
                                break
                        break
                    
                    turnless_node = node.getiterator("turnless")
                    for tnode in turnless_node:
                        self.turnless = int(tnode.text)
                        break
                    
                    addless_node = node.getiterator("addless")
                    for alnode in addless_node:
                        self.addless = int(alnode.text)
                        break
                    
                    break
        except:
            pass
        
        # 解析snextuser结点
        try:
            datastr = str(unicodedata)
            pos1 = datastr.find("<snextuser")
            pos2 = datastr.find("</snextuser>")
            if (pos1!=-1 and pos2!=-1):
                xmldata = datastr[pos1:pos2+"</snextuser>".__len__()]
                
                self.ui_mod.edit_recv.append(str("pos1:"+str(pos1)+",pos2:"+str(pos2)+"\nparse:"))
                self.ui_mod.edit_recv.append(xmldata)
                
                root = ElementTree.fromstring(xmldata)
                lst_node = root.getiterator("snextuser")
                for node in lst_node:
                    nodes = node.getiterator("currentuser")
                    for cnode in nodes:   
                        self.currentuser = int(cnode.text)
                        break                                    
                
                    turnless_node = node.getiterator("turnless")
                    for tnode in turnless_node:
                        self.turnless = int(tnode.text)
                        break
                    
                    addless_node = node.getiterator("addless")
                    for alnode in addless_node:
                        self.addless = int(alnode.text)
                        break
                    
                    break
        except:
            pass
        
        # 解析sboardcard结点
        try:
            datastr = str(unicodedata)
            pos1 = datastr.find("<sboardcard")
            pos2 = datastr.find("</sboardcard>")
            if (pos1!=-1 and pos2!=-1):
                xmldata = datastr[pos1:pos2+"</sboardcard>".__len__()]
                
                self.ui_mod.edit_recv.append(str("pos1:"+str(pos1)+",pos2:"+str(pos2)+"\nparse:"))
                self.ui_mod.edit_recv.append(xmldata)
                
                root = ElementTree.fromstring(xmldata)
                lst_node = root.getiterator("sboardcard")
                for node in lst_node:
                    self.turnless = 0                    
                    nodes = node.getiterator("currentuser")
                    for cnode in nodes:                
                        self.currentuser = int(cnode.text)
                        break
                    
                    turnless_node = node.getiterator("turnless")
                    for tnode in turnless_node:
                        self.turnless = int(tnode.text)
                        break
                    
                    addless_node = node.getiterator("addless")
                    for alnode in addless_node:
                        self.addless = int(alnode.text)
                        break
                    
                    break
        except:
            pass
        
        # 解析suseradd结点
        try:
            datastr = str(unicodedata)
            pos1 = datastr.find("<suseradd")
            pos2 = datastr.find("</suseradd>")
            if (pos1!=-1 and pos2!=-1):
                xmldata = datastr[pos1:pos2+"</suseradd>".__len__()]
                
                self.ui_mod.edit_recv.append(str("pos1:"+str(pos1)+",pos2:"+str(pos2)+"\nparse:"))
                self.ui_mod.edit_recv.append(xmldata)
                
                root = ElementTree.fromstring(xmldata)
                lst_node = root.getiterator("suseradd")
                for node in lst_node:
                    nodes = node.getiterator("chairid")
                    for cnode in nodes:
#                        add_node = node.getiterator("chip")
#                        for anode in add_node:
#                            addmoney = int(anode.text)
#                            if (self.turnless<addmoney):
#                                self.turnless = addmoney
                                                                        
                        if (int(cnode.text)==self.chairid):
                            gold_node = node.getiterator("money")
                            for gnode in gold_node:
                                self.gold = int(gnode.text)
                        break
                    break
        except:
            pass        
        
        if (self.currentuser!=-1 and self.currentuser==self.chairid):
            self.ui_mod.btn_add.setEnabled(True)
            self.ui_mod.btn_check.setEnabled(True)
            self.ui_mod.btn_follow.setEnabled(True)
            self.ui_mod.btn_giveup.setEnabled(True)
            self.tabmanager.ui_mod.tabWidget.setCurrentIndex(\
                 self.tabmanager.ui_mod.tabWidget.indexOf(self))
        else:
            self.ui_mod.btn_add.setEnabled(False)
            self.ui_mod.btn_check.setEnabled(False)
            self.ui_mod.btn_follow.setEnabled(False)
            self.ui_mod.btn_giveup.setEnabled(False)
            
        self.ui_mod.label_gold.setText(u"金币 ："+ str(self.gold))
        

    def connectionLost(self, reason): 
        self.emit(QtCore.SIGNAL('connectionLostSig(QString)'),unicode(reason))
                   
    def connectionLostSlot(self, unicodedreason):
        self.echoclient = None
        self.ip = None
        self.port = None
        self.ui_mod.btn_connect.setEnabled(True)
        self.ui_mod.btn_connect.setText(QtGui.QApplication.translate("tcptestorui", "连接", None, QtGui.QApplication.UnicodeUTF8))
        self.tabmanager.ui_mod.tabWidget.setTabText(
        self.tabmanager.ui_mod.tabWidget.indexOf(self), \
        QtGui.QApplication.translate("tcptestorui",\
        "未连接", None, QtGui.QApplication.UnicodeUTF8))
        self.ui_mod.edit_recv.append(u"连接断开"+unicodedreason)           
    
    
    class recv_edit(QtGui.QTextEdit):
        def __init__(self,parent=None):
            QtGui.QTextEdit.__init__(self,parent)
            self.createContextMenu()
                    
        def createContextMenu(self): 
            # 必须将ContextMenuPolicy设置为Qt.CustomContextMenu  
            # 否则无法使用customContextMenuRequested信号  
            self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)  
            self.customContextMenuRequested.connect(self.showContextMenu)  
      
            # 创建QMenu  
            self.contextMenu = QtGui.QMenu(self)  
            self.actionClear = self.contextMenu.addAction(u'清除')
            # 将动作与处理函数相关联  
            # 这里为了简单，将所有action与同一个处理函数相关联，  
            # 当然也可以将他们分别与不同函数关联，实现不同的功能  
            self.actionClear.triggered.connect(self.actionClearHandler) 
            
  
  
        def showContextMenu(self, pos): 
            # 菜单显示前，将它移动到鼠标点击的位置  
            self.contextMenu.move(self.mapToGlobal(QtCore.QPoint(0,0)+pos))
            self.contextMenu.show()  
      
      
        def actionClearHandler(self): 
            self.clear()
      
